package unimelb.discussiontracker.twitter.data.dao.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Repository;

import unimelb.discussiontracker.twitter.common.QueryControl;
import unimelb.discussiontracker.twitter.data.dao.IUserRankingDao;
import unimelb.discussiontracker.twitter.data.entity.UserRanking;

@Repository
public class UserRankingDao extends GenericDataAccessObject<UserRanking> implements IUserRankingDao {

    @Override
    public UserRanking findByUserTopicAndIntervalId(long userId, long topicId, long intervalId) {
        final Map<String, Object> params = new HashMap<String, Object>();
        params.put("userId", userId);
        params.put("topicId", topicId);
        params.put("intervalId", intervalId);
        return this.runSingleResultNamedQuery("UserRanking.FindByUserTopicAndIntervalId", params, null);
    }

    @Override
    public long countKeywordBasedRankings(long topicId, long intervalId) {
        final Map<String, Object> params = new HashMap<String, Object>();
        params.put("topicId", topicId);
        params.put("intervalId", intervalId);
        return this.runCountQuery("UserRanking.CountTopRankings", params, null);
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<UserRanking> findKeywordBasedRankings(long topicId, long intervalId, QueryControl queryControl) {
        String query = "SELECT ranking FROM UserRanking ranking WHERE ranking.topic.id = :topicId AND ranking.interval.id = :intervalId";
        query = appendOrderPart(query, queryControl.getSortBy(), queryControl.getSortOrder());

        final Map<String, Object> params = new HashMap<String, Object>();
        params.put("topicId", topicId);
        params.put("intervalId", intervalId);
        return this.runDynamicQuery(query, params, queryControl);
    }

    @Override
    public long countRankingsByTag(long tagId, long topicId, long intervalId) {
        final Map<String, Object> params = new HashMap<String, Object>();
        params.put("topicId", topicId);
        params.put("intervalId", intervalId);
        params.put("tagId", tagId);
        return this.runCountQuery("UserRanking.CountRankingsByTag", params, null);
    }

    @Override
    public List<UserRanking> findRankingsByTag(long tagId, long topicId, long intervalId, QueryControl queryControl) {
        String query = "SELECT DISTINCT ranking, ranking.user.name FROM UserRanking ranking, IN (ranking.user.ownTweets) tweet, IN (tweet.hashTags) tagAssoc WHERE tagAssoc.hashTag.id = :tagId AND ranking.topic.id = :topicId and ranking.interval.id = :intervalId";
        query = appendOrderPart(query, queryControl.getSortBy(), queryControl.getSortOrder());

        final Map<String, Object> params = new HashMap<String, Object>();
        params.put("topicId", topicId);
        params.put("intervalId", intervalId);
        params.put("tagId", tagId);

        List<UserRanking> result = new ArrayList<UserRanking>();
        for (Object obj : this.runDynamicQuery(query, params, queryControl)) {
            result.add((UserRanking) ((Object[]) obj)[0]);
        }
        return result;
    }

    private String appendOrderPart(String query, String sortBy, String sortOrder) {
        if ("name".equalsIgnoreCase(sortBy)) {
            return query + " ORDER BY ranking.user." + sortBy + " " + sortOrder;
        } else {
            return query + " ORDER BY ranking." + sortBy + " " + sortOrder;
        }
    }
}
